package com.banach.prema.executor;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.banach.prema.im.annotation.CallbackCommand;
import com.banach.prema.im.annotation.Callback;
import com.banach.prema.im.callback.CallBackResponse;
import com.banach.prema.im.config.AppConfig;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import java.io.BufferedReader;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author ajun
 * @Desc
 * @Date 2025/3/24 11:33
 */
@Component
public class ImCallbackExe implements ApplicationContextAware {
    private static Map<String, TargetMethod> targetMethodMap = new HashMap<String, TargetMethod>();
    @Autowired
    private AppConfig appConfig;


    @RequestMapping(value="/app/im/callback",method= RequestMethod.POST)
    public JSONObject callback(HttpServletRequest request) throws IOException {
        String sdkAppid = request.getParameter("SdkAppid");
        if(!appConfig.getSdkAppId().toString().equals(sdkAppid)){
            return CallBackResponse.createFallResponse("非法回调").toJson();
        }
        String callbackCommand = request.getParameter("CallbackCommand");
        String contenttype = request.getParameter("contenttype");
        String clientIP = request.getParameter("ClientIP");
        String optPlatform = request.getParameter("OptPlatform");
        String json = getBodyString(request);
        TargetMethod targetMethod = targetMethodMap.get(callbackCommand);
        try {
            Class parameterType = targetMethod.getMethod().getParameterTypes()[0];
            CallBackResponse res;
            if(parameterType==JSONObject.class){
                res = (CallBackResponse)targetMethod.getMethod().invoke(targetMethod.getObject(), JSON.parseObject(json));
            }else {
                res = (CallBackResponse)targetMethod.getMethod().invoke(targetMethod.getObject(), json);
            }
            return res.toJson();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            return CallBackResponse.createFallResponse(e.getMessage()).toJson();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
            return CallBackResponse.createFallResponse(e.getMessage()).toJson();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
            return CallBackResponse.createFallResponse(e.getMessage()).toJson();
        }
    }

    /**
     *
     * @param request
     * @return
     * @throws IOException
     */
    public static String getBodyString(HttpServletRequest request) throws IOException {
        String str = "";
        BufferedReader reader = request.getReader();
        String inputLine;
        while ((inputLine = reader.readLine()) != null) {
            str += inputLine;
        }
        reader.close();
        return str;
    }

    public static class TargetMethod{
        private Object object;
        private Method method;


        public TargetMethod(Object object, Method method) {
            super();
            this.object = object;
            this.method = method;
        }
        public Object getObject() {
            return object;
        }
        public void setObject(Object object) {
            this.object = object;
        }
        public Method getMethod() {
            return method;
        }
        public void setMethod(Method method) {
            this.method = method;
        }

    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext)
            throws BeansException {
        Map<String, Object> beanMap = applicationContext.getBeansWithAnnotation(Callback.class);
        for(Map.Entry<String, Object> entry : beanMap.entrySet()){
            Object object = entry.getValue();
            Method[] methods = object.getClass().getDeclaredMethods();
            for(Method method : methods){
                CallbackCommand callbackCommand = method.getAnnotation(CallbackCommand.class);
                if(callbackCommand!=null){
                    TargetMethod targetMethod = new TargetMethod(object, method);
                    targetMethodMap.put(callbackCommand.value(), targetMethod);
                }
            }
        }
    }
}
